package com.sun.designpatternsdemo.state.bean

import android.util.Log
import java.util.*

/**
 * 版权：xx公司 版权所有
 * @author sun
 * 版本：1.0
 * 创建日期：2021/7/1 10:26
 * 描述：实体
 * * 需求:
 * 现在为了提升销量，当用户每次转动手柄买商品的时候，有10%的几率赠送一瓶。
 * 下面开始重构，我们现在有5种状态，对应4个动作（投币、退币、转动手柄、发出商品），
 * 下面首先定义一个状态的超类型：
 * 状态的接口:
 */
interface State {
    //放钱
    fun insertMoney()

    //退钱
    fun backMoney()

    //转动曲柄
    fun turnCrank()

    //出商品
    fun dispense()
}

//已投入钱的状态
class HasMoneyState(var machine: VendingMachineBetter) : State {
    val random = Random()
    override fun insertMoney() {
        Log.e("HasMoneyState", "---您已经投过币了,不用再投了")
    }

    override fun backMoney() {
        Log.e("HasMoneyState", "---退币成功")
        machine.currentState = machine.noMoneyState
    }

    override fun turnCrank() {
        Log.e("HasMoneyState", "---你转动了手柄...")
        val winner = random.nextInt(10)
        if (winner == 0 && machine.count>1){
            machine.currentState = machine.winnerState
        }else{
            machine.currentState = machine.soldState
        }
    }

    override fun dispense() {
        Log.e("HasMoneyState", "---只有在 售出商品状态时才能出货!")
        throw IllegalStateException("非法状态!")
    }
}

//未投入钱的状态
class NoMoneyState(var machine: VendingMachineBetter) : State {
    override fun insertMoney() {
        Log.e("NoMoneyState", "---投币成功")
        machine.currentState = machine.hasMoneyState
    }

    override fun backMoney() {
        Log.e("NoMoneyState", "---您没投币就像退钱? 您这算抢!")
    }

    override fun turnCrank() {
        Log.e("NoMoneyState", "---您未投币就想摇杆,您在逗我吧!")
    }

    override fun dispense() {
        Log.e("NoMoneyState", "---这商品要是出了,我跟你姓")
        throw java.lang.IllegalStateException("非法状态")
    }
}

//未投入钱的状态
class SoldOutState(machine: VendingMachineBetter) : State {
    override fun insertMoney() {
        Log.e("SoldOutState", "---投币失败,商品已售罄...")
    }

    override fun backMoney() {
        Log.e("SoldOutState", "---您未投币,想退钱么?")
    }

    override fun turnCrank() {
        Log.e("SoldOutState", "---商品售罄，转动手柄也木有用...")
    }

    override fun dispense() {
        throw IllegalStateException("非法状态")
    }
}

//未投入钱的状态
class SoldState(var machine: VendingMachineBetter) : State {
    override fun insertMoney() {
        Log.e("SoldState", "---正在出货,请勿投币")
    }

    override fun backMoney() {
        Log.e("SoldState", "---正在出货,没有可退的钱")
    }

    override fun turnCrank() {

        Log.e("SoldState", "---正在出货,请勿重复摇动手柄")
    }

    override fun dispense() {
        machine.dispense()
        if (machine.count>0){
            machine.currentState = machine.noMoneyState
        }else{
            Log.e("SoldState", "---商品已经售罄")
            machine.currentState = machine.soldOutState
        }
    }
}

//中奖状态 :10%  1--10个随机数里面取一个
// * 中奖的状态，该状态下不会有任何用户的操作
class WinnerState(var machine: VendingMachineBetter) : State {
    override fun insertMoney() {
        throw IllegalStateException("非法操作!")
    }

    override fun backMoney() {
        throw IllegalStateException("非法操作!")
    }

    override fun turnCrank() {

        throw IllegalStateException("非法操作!")
    }

    override fun dispense() {
        machine.dispense()
        if (machine.count == 0){
            Log.e("WinnerState", "---商品已售罄,中奖失效...")
            machine.currentState = machine.soldOutState
        }else{
            if (machine.count>0){
                machine.currentState = machine.noMoneyState
            }else{
                machine.currentState = machine.soldOutState
            }
        }

    }
}

class VendingMachine(var count: Int = 0) {
    /**
     * 已投币
     */
    private var HAS_MONEY = 0

    /**
     * 未投币
     */
    private var NO_MONEY = 1

    /**
     * 售出商品
     */
    private var SOLD = 2

    /**
     * 商品售罄
     */
    private var SOLD_OUT = 3

    private var currentStatus = NO_MONEY

    /**
     * 商品数量
     */

    init {
        if (count > 0) {
            currentStatus = NO_MONEY
        }
    }

    fun insertMoney() {
        when (currentStatus) {
            NO_MONEY -> {//未投币
                currentStatus = HAS_MONEY
                Log.e("insertMoney", "---成功投入硬币")
            }
            HAS_MONEY -> Log.e("insertMoney", "---已经有硬币,无需投币")//已投币
            SOLD -> Log.e("insertMoney", "---请稍等...")//售出商品
            SOLD_OUT -> Log.e("insertMoney", "---商品已经售罄, 请勿投币")//商品售罄
        }
    }

    /**
     * 退币,任何状态用户都可能退币
     */
    fun backMoney() {
        when (currentStatus) {
            NO_MONEY -> Log.e("backMoney", "---您未投入硬币")//未投币
            HAS_MONEY -> {//已投币
                currentStatus = NO_MONEY
                Log.e("backMoney", "---退币成功")
            }
            SOLD -> Log.e("backMoney", "---您已经买了糖果...")//售出商品
            SOLD_OUT -> Log.e("backMoney", "---您未投币,想坑我钱吗?")//商品售罄
        }
    }

    /**
     * 转动手柄购买,任何状态都有可能转动手柄
     */
    fun turnCrank() {
        when (currentStatus) {
            NO_MONEY -> Log.e("turnCrank", "---请先投入硬币")
            HAS_MONEY -> {
                Log.e("turnCrank", "---正在出商品")
                currentStatus = SOLD
                dispense()
            }
            SOLD -> Log.e("turnCrank", "---连续转动也没用...")
            SOLD_OUT -> Log.e("turnCrank", "---商品已经售罄")
        }
    }

    /**
     * 发送商品
     */
    private fun dispense() {
        when (currentStatus) {
            NO_MONEY, HAS_MONEY, SOLD_OUT -> throw IllegalStateException(
                "非法的状态..."
            )
            SOLD -> {
                count--
                Log.e("dispense", "---发出商品...")
                currentStatus = if (count == 0) {
                    Log.e("dispense", "---商品售罄")
                    SOLD_OUT
                } else {
                    NO_MONEY
                }
            }
        }
    }


}

//自动售货机
class VendingMachineBetter(var count: Int = 0) {
    var currentState: State? = null
    val noMoneyState: State
    val hasMoneyState: State
    val soldState: State
    val soldOutState: State
    val winnerState: State

    init {
        noMoneyState = NoMoneyState(this)
        hasMoneyState = HasMoneyState(this)
        soldOutState = SoldOutState(this)
        soldState = SoldState(this)
        winnerState = WinnerState(this)
        if (count > 0) {
            currentState = noMoneyState
        }
    }

    //放钱
    fun insertMoney() {
        currentState?.insertMoney()
    }

    //退钱
    fun backMoney() {
        currentState?.backMoney()
    }

    //转动曲柄
    fun turnCrank() {
        currentState?.turnCrank()
        if (currentState == soldState || currentState == winnerState) {
            currentState?.dispense()//两种情况会出货
        }
    }

    //出商品
    fun dispense() {
        Log.e("VendingMachineBetter", "---发出一件商品")
        if (count > 0) {
            count--
        }
    }
}